package com.goa.service.impl;

import com.goa.entity.CurrentVoltage;
import com.goa.entity.DeviceBase;
import com.goa.mapper.CurrentVoltageMapper;
import com.goa.mapper.DeviceBaseMapper;
import com.goa.mapper.DeviceElectricityMapper;
import com.goa.mapper.DevicePowerMapper;
import com.goa.service.SmartBiService;
import com.goa.utils.DateUtil;
import com.goa.vo.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @author chuyongshuo
 * @version 1.0
 * @date 2024/10/22 8:41
 */
@Service
public class SmartBiServiceImpl implements SmartBiService {

    private static final Logger logger = LoggerFactory.getLogger(SmartBiServiceImpl.class);

    @Autowired
    DeviceBaseMapper deviceBaseMapper; //设备主表

    @Autowired
    CurrentVoltageMapper currentVoltageMapper;//电压电流表

    @Autowired
    DeviceElectricityMapper deviceElectricityMapper; //电度表

    @Autowired
    DevicePowerMapper devicePowerMapper;//电功率表

    // 假设阈值
    final double CURRENT_THRESHOLD = 1.5; // 电流阈值（单位：安培）
    final double VOLTAGE_THRESHOLD = 220; // 电压阈值（单位：伏特）

    // 电压量程
    final double VOLTAGE_380 = 380.0; // 380电压量程（单位：伏特）
    final double VOLTAGE_220 = 220.0; // 220电压量程（单位：伏特）


    //根据ID查询设备信息
    public AjaxResult getDeviceInfoById(String deviceId) {
        DeviceBase deviceBase = deviceBaseMapper.queryDeviceById(deviceId);
        if (deviceBase==null){
            return AjaxResult.error("暂无设备");
        }
        return AjaxResult.success(deviceBase);
    }

    //查询电流电压折线图
    public AjaxResult getDeviceStateSlicing(String deviceId, String dateType, String dateTime) {
        //开始时间戳  结束时间戳
        long[] timestamps =null;
        //存放数据库查询数据
        List<CurrentVoltage> currentVoltages =new ArrayList<>();
        //存放返回数据
        List<CurrentVoltageStateMonitorVo> currentVoltageStateMonitorVos = new ArrayList<>();
        //根据id查询当天设备
        DeviceBase deviceBase = deviceBaseMapper.queryDeviceById(deviceId);
        //获取设备是220v/380v
        Double voltageRange = deviceBase.getVoltageRange();
        Boolean typeFlag =true;//默认380方法
        if (380.0d!=voltageRange){
            typeFlag=false;//其他全部默认220V处理方法
        }
        switch (dateType) {
            case "y":
                System.out.println("处理年逻辑");
                break;
            case "m":
                System.out.println("处理月逻辑");
                break;
            default: //默认为d类型
                if (dateTime==null||"".equals(dateTime)){
                    timestamps = DateUtil.getTimestampsForPreviousDay();
                    //如果为空 默认为查询昨日数据
                    dateTime=DateUtil.getYesterdayDate();
                }
                //如果日期不为空,那么发送哪一天就查询那一天数据
                timestamps = DateUtil.getTimestamps(dateTime);
                logger.info("电压电流 处理类型：日和其他 开始时间戳 = {}========结束时间戳 ={}",timestamps[0],timestamps[1]);
                currentVoltages =currentVoltageMapper.selectCurrentVoltageByTime(deviceId,timestamps[0],timestamps[1]);
                if (typeFlag){
                    //380v
                    currentVoltageStateMonitorVos=invoker380VCurrentVoltageMethod(currentVoltages);
                }else {
                    //220
                    currentVoltageStateMonitorVos=invoker220VCurrentVoltageMethod(currentVoltages);
                }
                break;
        }

        //获取第一个数据
        Long startTime = Long.valueOf(currentVoltages.get(0).getTimestamp());
        //获取最后一个数据
        Long endTime = Long.valueOf(currentVoltages.get(currentVoltages.size()-1).getTimestamp());

        //判断数据开始时间戳与0点相差是否5分钟秒以上
        boolean greaterThanSeconds = DateUtil.isDistanceGreaterThanSeconds(0, startTime, 300);
        if (greaterThanSeconds){
            long duration = calculateDuration(timestamps[0],startTime);
            CurrentVoltageStateMonitorVo beginMonitor = new CurrentVoltageStateMonitorVo("停机",duration,timestamps[0],startTime);
            currentVoltageStateMonitorVos.add(0,beginMonitor); //距离0点的数据添加到第一个索引处
        }
        //判断当前时间戳与24点时间戳相差30秒以上。
        boolean distanceGreaterThanSeconds = DateUtil.isDistanceGreaterThanSeconds(1, endTime, 300);
        if (distanceGreaterThanSeconds){
            long duration = calculateDuration(endTime,timestamps[1]);
            CurrentVoltageStateMonitorVo beginMonitor = new CurrentVoltageStateMonitorVo("停机",duration,endTime,timestamps[1]);
            currentVoltageStateMonitorVos.add(beginMonitor);//距离24点的数据添加到最后一个
        }

        Map<String, Long> status = calculatDeviceStatus(currentVoltageStateMonitorVos);
        Map<String, Object> returnMap = new HashMap<>();
        returnMap.put("dataList",currentVoltageStateMonitorVos);
        returnMap.put("status",status);
        return AjaxResult.success(returnMap);
    }

    //获取能耗趋势图
    public AjaxResult getEnergyConsumption(String deviceId, String dateType, String dateTime) {
        List<DeviceElectricityVo>  deviceElectricityVoList =new ArrayList<>();
        String startTime =null; //开始时间
        String endTime =null; //结束时间
        switch (dateType) {
            case "y":
                //获取当前年的开始时间和结束时间。
                String[] yearStartEnd = DateUtil.getYearStartEnd(Integer.valueOf(dateTime));//2024
                startTime=yearStartEnd[0]+" 00:00:00";
                endTime=yearStartEnd[1]+" 23:59:59";
                deviceElectricityVoList =deviceElectricityMapper.selectElectricityByYear(deviceId,startTime,endTime);
                break;
            case "m":
                //如果按月的话,分别汇报一个月所有天的耗电量;
                //获取指定月的第一天和最后一天。
                String[] firstAndLastDayOfMonth = DateUtil.getFirstAndLastDayOfMonth(dateTime);//2024-10
                startTime=firstAndLastDayOfMonth[0]+" 00:00:00"; //2024-09-10 00:00:00
                endTime=firstAndLastDayOfMonth[1]+" 23:59:59"; //2024-09-13 23:59:59
                deviceElectricityVoList=deviceElectricityMapper.selectElectricityByMonth(deviceId,startTime,endTime);
                break;
            default: //默认为d类型
                if (dateTime==null||"".equals(dateTime)){ //2024-10-10
                    //如果为空 默认为查询昨日数据
                    dateTime=DateUtil.getYesterdayDate();
                }
                startTime =dateTime+" 00:00:00";
                endTime =dateTime+" 23:59:59";
                deviceElectricityVoList =  deviceElectricityMapper.selectElectricityByDay(deviceId,startTime,endTime);
                break;
        }

        return AjaxResult.success(deviceElectricityVoList);
    }

    //动态查询电流电压折线图
    public AjaxResult plotCurrentVoltageGraph(String deviceId, String dateType, String dateTime) {
        PlotCurrentVoltageGraphVo plotCurrentVoltageGraphVo = new PlotCurrentVoltageGraphVo();
        //获取到设备基本信息
        DeviceBase deviceBase = deviceBaseMapper.queryDeviceById(deviceId);
        // 初始化用于存储整点电流和电压的数组
        Map<String,List<Double>> correctMap = new HashMap<>();
        //用于储存异常的电流电压数据
        Map<String,List<Double>> errorInfo =  new HashMap<>();
        String startTime =null; //开始时间
        String endTime =null; //结束时间
        switch (dateType) {
            case "y":
                //获取当前年的开始时间和结束时间。
                String[] yearStartEnd = DateUtil.getYearStartEnd(Integer.valueOf(dateTime));//2024
                startTime=yearStartEnd[0]+" 00:00:00";
                endTime=yearStartEnd[1]+" 23:59:59";
                break;
            case "m":
                //如果按月的话,分别汇报一个月所有天的耗电量;
                //获取指定月的第一天和最后一天。
                String[] firstAndLastDayOfMonth = DateUtil.getFirstAndLastDayOfMonth(dateTime);//2024-10
                startTime=firstAndLastDayOfMonth[0]+" 00:00:00"; //2024-09-10 00:00:00
                endTime=firstAndLastDayOfMonth[1]+" 23:59:59"; //2024-09-13 23:59:59
                break;
            default: //默认为d类型
                if (dateTime==null||"".equals(dateTime)){ //2024-10-10
                    //如果为空 默认为查询昨日数据
                    dateTime=DateUtil.getYesterdayDate();
                }
                startTime =dateTime+" 00:00:00";
                endTime =dateTime+" 23:59:59";
                //获取到24小时整点的数据
                List<CurrentVoltage> currentVoltageList =  currentVoltageMapper.selectCurrentVoltageByTimeOnHour(deviceId,startTime,endTime);
                //获取所有数据
                List<CurrentVoltage> abnormalCurrentVoltageList = currentVoltageMapper.getAbnormalCurrentVoltage(deviceId,startTime,endTime);

                if (VOLTAGE_380==deviceBase.getVoltageRange()) {
                   //380v处理逻辑
                    if (currentVoltageList != null && currentVoltageList.size() > 0) {
                        for (CurrentVoltage currentVoltage : currentVoltageList) {
                            List<Double> values = new ArrayList<>();
                            double aCurrent = currentVoltage.getACurrent();
                            double bCurrent = currentVoltage.getBCurrent();
                            double cCurrent = currentVoltage.getCCurrent();
                            double aVoltage = currentVoltage.getAVoltage();
                            double bVoltage = currentVoltage.getBVoltage();
                            double cVoltage = currentVoltage.getCVoltage();
                            // 将时间戳和对应的电流电压值存入 correctInfo
                            values.add(aCurrent);
                            values.add(bCurrent);
                            values.add(cCurrent);
                            values.add(aVoltage);
                            values.add(bVoltage);
                            values.add(cVoltage);
                            correctMap.put(currentVoltage.getCreatedAt().toString(), values);
                        }
                        //找出异常值
                        for (CurrentVoltage currentVoltage : abnormalCurrentVoltageList) {
                            List<Double> values = new ArrayList<>();
                            double aCurrent = currentVoltage.getACurrent();
                            double aVoltage = currentVoltage.getAVoltage();
                            if (aCurrent>15||aVoltage>380){
                                //异常数据
                                values.add(aCurrent);
                                values.add(aVoltage);
                                correctMap.put(currentVoltage.getCreatedAt().toString(), values);
                            }
                        }
                    }

                }else {
                    //220v处理逻辑
                    if (currentVoltageList != null && currentVoltageList.size() > 0) {
                        for (CurrentVoltage currentVoltage : currentVoltageList) {
                            List<Double> values = new ArrayList<>();
                            double aCurrent = currentVoltage.getACurrent();
                            double aVoltage = currentVoltage.getAVoltage();
                            // 将时间戳和对应的电流电压值存入 correctInfo
                            values.add(aCurrent);
                            values.add(aVoltage);
                            correctMap.put(currentVoltage.getCreatedAt().toString(), values);
                        }
                        //找出异常值
                        for (CurrentVoltage currentVoltage : abnormalCurrentVoltageList) {
                            List<Double> values = new ArrayList<>();
                            double aCurrent = currentVoltage.getACurrent();
                            double aVoltage = currentVoltage.getAVoltage();
                            if (aCurrent>15||aVoltage>380){
                                //异常数据
                                values.add(aCurrent);
                                values.add(aVoltage);
                                correctMap.put(currentVoltage.getCreatedAt().toString(), values);
                            }
                        }
                    }
                }
                break;
        }
        // 时间格式化器
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 将Map按时间排序
        Map<String, List<Double>> sortedMap = new LinkedHashMap<>();
        correctMap.entrySet()
                .stream()
                .sorted((entry1, entry2) -> {
                    // 将时间字符串转化为 LocalDateTime 对象后进行比较
                    LocalDateTime time1 = LocalDateTime.parse(entry1.getKey(), formatter);
                    LocalDateTime time2 = LocalDateTime.parse(entry2.getKey(), formatter);
                    return time1.compareTo(time2);
                })
                .forEachOrdered(entry -> sortedMap.put(entry.getKey(), entry.getValue()));
        plotCurrentVoltageGraphVo.setCurrentVoltageMap(sortedMap);
        return AjaxResult.success(plotCurrentVoltageGraphVo);
    }

    //统计设备状态
    public AjaxResult getDeviceStatusCount(String deviceId, String dateType, String dateTime) {
        return null;
    }

    //获取电功率趋势图
    public AjaxResult getPowerTrendChart(String deviceId, String dateType, String dateTime) {
        List<PowerVo>  powerVoList =new ArrayList<>();
        String startTime =null; //开始时间
        String endTime =null; //结束时间
        switch (dateType) {
            case "y":
                //获取当前年的开始时间和结束时间。
                String[] yearStartEnd = DateUtil.getYearStartEnd(Integer.valueOf(dateTime));//2024
                startTime=yearStartEnd[0]+" 00:00:00";
                endTime=yearStartEnd[1]+" 23:59:59";
                break;
            case "m":
                //如果按月的话,分别汇报一个月所有天的耗电量;
                //获取指定月的第一天和最后一天。
                String[] firstAndLastDayOfMonth = DateUtil.getFirstAndLastDayOfMonth(dateTime);//2024-10
                startTime=firstAndLastDayOfMonth[0]+" 00:00:00"; //2024-09-10 00:00:00
                endTime=firstAndLastDayOfMonth[1]+" 23:59:59"; //2024-09-13 23:59:59
                break;
            default: //默认为d类型
                if (dateTime==null||"".equals(dateTime)){ //2024-10-10
                    //如果为空 默认为查询昨日数据
                    dateTime=DateUtil.getYesterdayDate();
                }
                startTime =dateTime+" 00:00:00";
                endTime =dateTime+" 23:59:59";
                powerVoList =  devicePowerMapper.selectPowerByDay(deviceId,startTime,endTime);
                break;
        }

        return AjaxResult.success(powerVoList);
    }

    //处理220v电压电流方法
    private List<CurrentVoltageStateMonitorVo> invoker220VCurrentVoltageMethod(List<CurrentVoltage> currentVoltages) {
        List<CurrentVoltageStateMonitorVo> result = new ArrayList<>();
        for (int i = 0; i < currentVoltages.size(); i++) {
            CurrentVoltage voltage = currentVoltages.get(i);
            Long currentTimestamp = voltage.getTimestamp();
            double aCurrent = voltage.getACurrent(); //220v电流
            double aVoltage = voltage.getAVoltage();//220v电压
            // 计算时间差 上下两天数据时间差大于 3分钟以上认为停机（相当于网关断电，不能发送数据）
            long timeDifference=0;//i的数据和i+1的数据时间戳差值
            if (i!=currentVoltages.size()-1){
                timeDifference = calculateTimeDifference(currentTimestamp,currentVoltages.get(i + 1).getTimestamp()); //返回相差的毫秒值
            }
            String newState="停机"; //循环内状态
            if (timeDifference > 60*1*1000) { // 3分钟以上认为停机
                newState = "停机";
            } else {
                if (aCurrent < CURRENT_THRESHOLD &&
                        aVoltage < VOLTAGE_THRESHOLD) {
                    newState = "待机"; // 待机状态
                } else if (aCurrent==0){
                    newState = "停机"; // 正常运行状态
                }else {
                    newState="运行";
                }
            }

            voltage.setStatus(newState);
            if (i > 0) {
                String previousState = currentVoltages.get(i - 1).getStatus().toString();
                // 如果状态改变，更新上一个状态的结束时间
                if (!newState.equals(previousState)) {
                    if (!result.isEmpty()) {
                        CurrentVoltageStateMonitorVo stateDuration = result.get(result.size() - 1);
                        stateDuration.setEndTime(currentTimestamp);
                    }
                }
            }

            // 如果是第一个状态或当前状态与前一个状态不同，添加新状态
            if (i == 0 || !newState.equals(currentVoltages.get(i - 1).getStatus().toString())) {
                result.add(new CurrentVoltageStateMonitorVo(newState, 0,currentTimestamp, null));
            }
        }
        // 更新最后一个状态的结束时间
        if (!result.isEmpty() && !currentVoltages.isEmpty()) {
            CurrentVoltageStateMonitorVo lastStateDuration = result.get(result.size() - 1);
            lastStateDuration.setEndTime(currentVoltages.get(currentVoltages.size() - 1).getTimestamp());
        }
        return result;
    }

    //处理380v电压电流方法
    private List<CurrentVoltageStateMonitorVo> invoker380VCurrentVoltageMethod(List<CurrentVoltage> currentVoltages) {
        List<CurrentVoltageStateMonitorVo> result = new ArrayList<>();
        for (int i = 0; i < currentVoltages.size(); i++) {
            CurrentVoltage voltage = currentVoltages.get(i);
            Long currentTimestamp = voltage.getTimestamp();
            double aCurrent = voltage.getACurrent();
            double bCurrent = voltage.getBCurrent();
            double cCurrent = voltage.getCCurrent();
            double aVoltage = voltage.getAVoltage();
            double bVoltage = voltage.getBVoltage();
            double cVoltage = voltage.getCVoltage();

            // 计算时间差 上下两天数据时间差大于 3分钟以上认为停机（相当于网关断电，不能发送数据）
            long timeDifference=0;//i的数据和i+1的数据时间戳差值
            if (i!=currentVoltages.size()-1){
                timeDifference = calculateTimeDifference(currentTimestamp,currentVoltages.get(i + 1).getTimestamp()); //返回相差的毫秒值
            }
            String newState="停机"; //循环内状态
            if (timeDifference > 60*1*1000) { // 3分钟以上认为停机
                newState = "停机";
            } else {
                if (aCurrent < CURRENT_THRESHOLD && bCurrent < CURRENT_THRESHOLD && cCurrent < CURRENT_THRESHOLD &&
                        aVoltage < VOLTAGE_THRESHOLD && bVoltage < VOLTAGE_THRESHOLD && cVoltage < VOLTAGE_THRESHOLD) {
                    newState = "待机"; // 待机状态
                } else if (aCurrent==0){
                    newState = "停机"; // 正常运行状态
                }else {
                    newState="运行";
                }
            }

            voltage.setStatus(newState);
            if (i > 0) {
                String previousState = currentVoltages.get(i - 1).getStatus().toString();
                // 如果状态改变，更新上一个状态的结束时间
                if (!newState.equals(previousState)) {
                    if (!result.isEmpty()) {
                        CurrentVoltageStateMonitorVo stateDuration = result.get(result.size() - 1);
                        stateDuration.setEndTime(currentTimestamp);
                    }
                }
            }
            // 如果是第一个状态或当前状态与前一个状态不同，添加新状态
            if (i == 0 || !newState.equals(currentVoltages.get(i - 1).getStatus().toString())) {
                result.add(new CurrentVoltageStateMonitorVo(newState, 0,currentTimestamp, null));
            }
        }
        // 更新最后一个状态的结束时间
        if (!result.isEmpty() && !currentVoltages.isEmpty()) {
            CurrentVoltageStateMonitorVo lastStateDuration = result.get(result.size() - 1);
            lastStateDuration.setEndTime(currentVoltages.get(currentVoltages.size() - 1).getTimestamp());
        }
        return result;
    }


    // 方法：计算时间差
    private long calculateDuration(long startTime, long endTime) {
        return (endTime - startTime) / 1000/60; // 转换分钟
    }

    // 计算两个时间戳之间的秒数差
    private static long calculateTimeDifference(Long startTime, Long endTime) {
        // 假设时间格式为 "yyyy-MM-dd'T'HH:mm:ss"
        return endTime - startTime;

    }

    //统计各个状态下时间占比情况
    private static Map<String, Long> calculatDeviceStatus(List<CurrentVoltageStateMonitorVo> records) {
        Map<String, Long> totalDurations = new HashMap<>();

        for (CurrentVoltageStateMonitorVo record : records) {
            Long startTime = Long.valueOf(record.getStartTime());
            Long endTime = Long.valueOf(record.getEndTime());
            Long duration= endTime-startTime;
            // 累加到对应的状态
            totalDurations.put(record.getMachineState(), (totalDurations.getOrDefault(record.getMachineState(), 0L) + duration));
        }

        return totalDurations;
    }

}
